package com.alan.http;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class HttpUtils {


    private static OkHttpClient mOkHttpClient;

    private static final int NETWORK_TIMEOUT = 600;
    private static final String CHARSET_NAME = "UTF-8";
    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
    public static final MediaType MEDIA_TYPE_APPLICATION = MediaType.parse("application/x-www-form-urlencoded");
    public static final MediaType MEDIA_TYPE_APPLICATION_FILE = MediaType.parse("application/octet-stream");

    private static final String TAG = "ALAN_HttpUtils";

    private static Handler handler;

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.readTimeout(NETWORK_TIMEOUT, TimeUnit.SECONDS);
        builder.writeTimeout(NETWORK_TIMEOUT, TimeUnit.SECONDS);
        builder.connectTimeout(NETWORK_TIMEOUT, TimeUnit.SECONDS);
        builder.hostnameVerifier((hostname, session) -> true);
        mOkHttpClient = builder.build();
        handler = new Handler(Looper.getMainLooper());
    }

    public static void getAsync(HttpParameter parameter) {
        getAsync(parameter, null, false);
    }

    public static void getAsync(HttpParameter parameter, OnHttpCallback callback) {
        getAsync(parameter, callback, true);
    }

    /**
     * 异步get请求
     *
     * @param parameter
     */
    public static void getAsync(HttpParameter parameter, OnHttpCallback callback, boolean isResponseOnMainThread) {
        try {
            Request request = getRequestByGet(parameter.getUrl(), parameter.getMap(), parameter.isEncoding());
            mOkHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.w(TAG, "getAsync onFailure");
                    Log.w(TAG, Log.getStackTraceString(e));
                    if (isResponseOnMainThread) {
                        handler.post(() -> {
                            if (null != callback) {
                                callback.onFailure(e);
                            }
                        });
                    } else {
                        if (null != callback) {
                            callback.onFailure(e);
                        }
                    }
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Log.d(TAG, "getAsync onResponse");
                    try {
                        String responseStr = getResponseStr(response);
                        if (isResponseOnMainThread) {
                            handler.post(() -> {
                                if (null != callback) {
                                    callback.onSuccess(responseStr);
                                }
                            });
                        } else {
                            if (null != callback) {
                                callback.onSuccess(responseStr);
                            }
                        }
                    } catch (IOException e) {
                        Log.w(TAG, "getAsync onResponse error:" + e.getMessage());
                        onFailure(null, e);
                    }
                }
            });
        } catch (Throwable e) {
            Log.w(TAG, Log.getStackTraceString(e));
            if (null != callback) {
                callback.onFailure(e);
            }
        }
    }

    public static String getSync(HttpParameter parameter) throws Throwable {
        Request request = getRequestByGet(parameter.getUrl(), parameter.getMap(), parameter.isEncoding());
        Response response = mOkHttpClient.newCall(request).execute();
        return getResponseStr(response);
    }

    private static String getResponseStr(Response response) throws IOException {
        if (response.isSuccessful()) {
            String responseUrl = response.body().string();
            Log.d(TAG, "response data:" + responseUrl);
            return responseUrl;
        }
        return "";
    }

    private static Request getRequestByGet(String url, Map<String, String> map, boolean isEncoding) throws IOException {
        String param = getContentFromMap(map, isEncoding);
        url += "?" + param;
        Log.d(TAG, "url:" + url);
        return new Request.Builder().tag(url).url(url).build();
    }

    public static String getContentFromMap(Map<String, String> params, boolean isEncoding) throws IOException {
        if (null == params)
            return "";
        StringBuilder sb = new StringBuilder();
        Set<String> keys = params.keySet();
        for (String key : keys) {
            String value = params.get(key);
            if (value != null) {
                sb.append(key).append('=').append(isEncoding ? URLEncoder.encode(value, CHARSET_NAME) : value).append('&');
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        Log.d(TAG, "data:" + sb.toString());
        return sb.toString();
    }

    public interface OnHttpCallback {

        void onSuccess(String message);

        void onFailure(Throwable e);
    }

}
